#####################################################################
#                                                                   #
#  THIS IS A SOURCE CODE FILE FROM A PROGRAM TO INTERACT WITH THE   #
# LBRY PROTOCOL ( lbry.com ). IT WILL USE THE LBRY SDK ( lbrynet )  #
# FROM THEIR REPOSITORY ( https://github.com/lbryio/lbry-sdk )      #
# WHICH I GONNA PRESENT TO YOU AS A BINARY. SINCE I DID NOT DEVELOP #
# IT AND I'M LAZY TO INTEGRATE IN A MORE SMART WAY. THE SOURCE CODE #
# OF THE SDK IS AVAILABLE IN THE REPOSITORY MENTIONED ABOVE.        #
#                                                                   #
#      ALL THE CODE IN THIS REPOSITORY INCLUDING THIS FILE IS       #
# (C) J.Y.Amihud and Other Contributors 2021. EXCEPT THE LBRY SDK.  #
# YOU CAN USE THIS FILE AND ANY OTHER FILE IN THIS REPOSITORY UNDER #
# THE TERMS OF GNU GENERAL PUBLIC LICENSE VERSION 3 OR ANY LATER    #
# VERSION. TO FIND THE FULL TEXT OF THE LICENSE GO TO THE GNU.ORG   #
# WEBSITE AT ( https://www.gnu.org/licenses/gpl-3.0.html ).         #
#                                                                   #
# THE LBRY SDK IS UNFORTUNATELY UNDER THE MIT LICENSE. IF YOU ARE   #
# NOT INTENDING TO USE MY CODE AND JUST THE SDK. YOU CAN FIND IT ON #
# THEIR OFFICIAL REPOSITORY ABOVE. THEIR LICENSE CHOICE DOES NOT    #
# SPREAD ONTO THIS PROJECT. DON'T GET A FALSE ASSUMPTION THAT SINCE #
# THEY USE A PUSH-OVER LICENSE, I GONNA DO THE SAME. I'M NOT.       #
#                                                                   #
# THE LICENSE CHOSEN FOR THIS PROJECT WILL PROTECT THE 4 ESSENTIAL  #
# FREEDOMS OF THE USER FURTHER, BY NOT ALLOWING ANY WHO TO CHANGE   #
# THE LICENSE AT WILL. SO NO PROPRIETARY SOFTWARE DEVELOPER COULD   #
# TAKE THIS CODE AND MAKE THEIR USER-SUBJUGATING SOFTWARE FROM IT.  #
#                                                                   #
#####################################################################

# Preparing the executable of lbrynet to be running. If we don't that
# there will be a nasty error of permission being denied.

import os
os.system("chmod u+x flbry/lbrynet")

# I'm not trying to make it pretty. I'm trying to make it snappy.
# It's FastLBRY not SlowLBRY.

import gi
import threading
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import GLib

# It's gonna take a couple of things to make the button run
from flbry import connect
from flbry import parse
from flbry import settings
from flbry import url
from flbry import ui
from flbry import claim_search
from flbry import fetch
from flbry import publish
from flbry import downloads
from flbry import analytics
from flbry import livestreams
from flbry import suggest
from flbry import odysee

settings.make_sure_file_exists()

##########################################################################
#                                                                        #
#                   THE MAIN WINDOW OF FASTLBRY GTK                      #
#                                                                        #
##########################################################################

win = Gtk.Window()                    # Make a GTK window object
win.connect("destroy", Gtk.main_quit) # If you close the window, program quits
win.set_title("FastLBRY GTK")         # Title
win.set_default_icon_from_file("icon.png") # Icon
win.set_size_request(800, 900)        # Minimum size

##########################################################################
#                                                                        #
#            GLOBAL VARIABLES HACK ( adding things to 'win' )            #
#                                                                        #
##########################################################################

# This hack is very simple. Our main Gtk.Window() is a class to which we
# can add variables later on. Like the example you see below.
# This way, giving some function only 'win' and nothing else, will give
# that other function the entire list of global variable ( added this way ).

win.settings = settings.load()      # Settings
win.SDK_running = connect.check()   # Is the SDK running ( from 0 to 1  to draw progress bar)
win.resolved = {}                   # Last resolved data
win.commenting = {}                 # Data for while chatting in comments
win.subs = []                       # What you are subscribed to
win.tabs = []                       # List of Gtk.Notebook tabs
win.resolve_tab = 0                 # What tab to resolve the page
win.notebook = Gtk.Notebook()       # Tabs object
win.download_buttons = {}           # Keep alive handlers for Download buttons
win.downloads = {}                  # Data for the Downloads window

##########################################################################
#                                                                        #
#                              TOP PANNEL                                #
#                                                                        #
##########################################################################

# Gtk.HeaderBar() is like a box but it draws itself in the headerbar insead
# of in the window itself.

pannel = Gtk.HeaderBar()
pannel.set_show_close_button(True)
win.set_titlebar(pannel)   # Dumbasses wrote GTK

# Untill the user connected to the SDK,  search and other functions should
# not work. So we split the pannel into two parts. The other one is a
# normal box.

restofpannel = Gtk.HBox() # H for Horrizontal 
pannel.pack_end(restofpannel)


############## CONNECT BUTTON ################

# Connect button will also be a disconnect button


# Icons for both
icon_connect = ui.icon(win, "network-wired")
icon_disconnect = ui.icon(win, "network-wired-disconnected")

# Boxes for both
connect_box = Gtk.HBox()
disconnect_box = Gtk.HBox()

# Connect box 
connect_box.pack_start(icon_connect, False, False, False)
connect_box.set_tooltip_text("Connect to LBRY Network")
connect_box.pack_start(Gtk.Label("Connect "), False, False, False)

# Disconnect box 
disconnect_box.pack_start(icon_disconnect, False, False, False)
disconnect_box.set_tooltip_text("Disconnect from LBRY Network")
disconnect_box.pack_start(Gtk.Label("Disconnect "), False, False, False)

# By whether SDK was running while the software was launched
# we present the correct button to the user and set the rest-of-pannel
# accordingly.

if win.SDK_running:
    title = disconnect_box
    restofpannel.set_sensitive(True)
else:
    title = connect_box
    restofpannel.set_sensitive(False)


connect_disconncet_button = Gtk.Button()
connect_disconncet_button.add(title)
connect_disconncet_button.set_relief(Gtk.ReliefStyle.NONE)
pannel.pack_start(connect_disconncet_button)#, False, False, False)

############### CONNECT / DISCONNECT BUTTONS FUNCTION ################

# The button should do something.

def connect_disconnect_function(w):
    
    w.set_sensitive(False)

    dynamic_box = win.tabs[win.notebook.get_current_page()]["box"]

    for i in dynamic_box.get_children():
            i.destroy()

    progress_connect = Gtk.ProgressBar(show_text=True)
    dynamic_box.pack_start(progress_connect, True, True, 30)
    win.show_all()

    def do_sdk(w, pb):
        wasrunning = win.SDK_running
        if win.SDK_running == 1:
            connect.stop()
        else:
            connect.start()

        def update_pb(pb):
            pb.set_fraction(win.SDK_running)
            pb.set_text("Connecting: "+str(int(round(win.SDK_running*100)))+"%")
            
        def update_buttons(w):
            for i in dynamic_box.get_children():
                i.destroy()
            w.get_child().destroy()
            if win.SDK_running == 1:
                w.add(disconnect_box)
                restofpannel.set_sensitive(True)
            else:
                w.add(connect_box)
                restofpannel.set_sensitive(False)
            w.show_all()
            w.set_sensitive(True)
            if win.SDK_running == 1:
                load_following()
                load_channel(win)
                check_lock_button()
                ui.notify(win, "Connected to LBRY")

        if wasrunning == 0:
            while True:    
                win.SDK_running = connect.check()
                if win.SDK_running == 1:
                    break
                GLib.idle_add(update_pb, pb)
            
        GLib.idle_add(update_buttons, w)
        

    load_thread = threading.Thread(target=do_sdk, args=(w, progress_connect))
    load_thread.setDaemon(True)
    load_thread.start()
            

connect_disconncet_button.connect("clicked", connect_disconnect_function)


##########################################################################
#                                                                        #
#                               LOCK BUTTON                              #
#                                                                        #
##########################################################################




win.lock_button = Gtk.ToggleButton()

def check_lock_button():
    try:
        wallet_status = fetch.lbrynet("wallet_status")
    except:
        wallet_status = {}
    if  wallet_status.get("is_locked"):
        win.lock_button.set_active(True)

    if not win.settings["lock_password"]:
        win.lock_button.set_sensitive(False)
    else:
        win.lock_button.set_sensitive(True)

check_lock_button()
win.lock_button.set_tooltip_text("Lock / Unlock LBRY wallet. \n\n While the wallet is locked, no transaction could be signed. So nobody could use the running SDK to harm you.\n\nTo set the password look into settings.")
win.lock_button.set_relief(Gtk.ReliefStyle.NONE)
win.lock_button.add(ui.icon(win, "system-lock-screen-symbolic"))
restofpannel.pack_start(win.lock_button, False, False, False)

def lock_unlock(w):

    passw = win.settings["lock_password"]

    wallets = fetch.lbrynet("wallet_list")
    ID = wallets["items"][0]["id"]
    
    if w.get_active():
        # If we are locking
        print(fetch.lbrynet("wallet_encrypt", {"new_password":passw}))
        print(fetch.lbrynet("wallet_lock", {"wallet_id":ID}))

    else:
        # If decrypt
        print(fetch.lbrynet("wallet_unlock", {"password":passw, "wallet_id":ID}))
        print(fetch.lbrynet("wallet_decrypt", {"wallet_id":ID}))
        

    print("I AM FUCKING PRESSED")

        
win.lock_button.connect("clicked", lock_unlock)




##########################################################################
#                                                                        #
#                             PUBLISH BUTTON                             #
#                                                                        #
##########################################################################

restofpannel.pack_start(Gtk.VSeparator(), True, True, 20)

publ = Gtk.Button()
publ.set_tooltip_text("Publish to LBRY")
publ.set_relief(Gtk.ReliefStyle.NONE)
publ.add(ui.icon(win, "list-add"))
restofpannel.pack_start(publ, False, False, False)
def do_publish(w):
    publish.window(win)
publ.connect("clicked", do_publish)

restofpannel.pack_start(Gtk.VSeparator(), True, True, 20)

##########################################################################
#                                                                        #
#                           SEARCH / URL BAR                             #
#                                                                        #
##########################################################################


# Note that I add this directly into the 'win' to make it a global variable.
# This let's me to start any url from anywhere in the software.

win.url = Gtk.Entry() # Gtk.SearchEntry() also looks good, but nah
win.url.set_size_request(400,40)
restofpannel.pack_start(win.url, True, True, False)

####### SEARCH FUNCTION #######

def search(w):

    if win.resolve_tab == "current":
        win.resolve_tab = win.notebook.get_current_page()
    
    try:
        dynamic_box = win.tabs[win.resolve_tab]["box"]
    except:

        new_tab()
        dynamic_box = win.tabs[win.resolve_tab]["box"]
        

    
    
    # DRAG AND DROP FOR PUBLISH
    if win.url.get_text().startswith("file://") or os.path.exists(win.url.get_text()):

        # TODO: Some filenames include weird characters like %20 for spacebar and
        # stuff like that. We need to filter that out.
        
        filepath = win.url.get_text().replace("file://", "")
        publish.window(win, {"file_path":filepath})
        win.url.set_text("")
        return


    for i in dynamic_box.get_children():
        i.destroy()

    ## IF WE ARE NOT FORCING IT TO SEACH, IT WILL TRY TO RESOLVE THE LBRY URL FIRST ##
        
    if not force_search.get_active() or win.url.get_text().startswith("lbry://"):
        win.url.set_text(parse.bar(win.url.get_text()))

        ltext = win.url.get_text()
        ltext = ltext[ltext.rfind("/")+1:]
        win.tabs[win.resolve_tab]["label"].set_text(ltext[:10]+"...")
        win.tabs[win.resolve_tab]["label"].set_tooltip_text(win.url.get_text())
        
        resolve = ui.load(win, url.resolve, url.render_resolve, w, win,  win.url.get_text())
        dynamic_box.pack_start(resolve, True, True, True)
        win.show_all()
    else:
        resolve = ui.load(win, claim_search.find, claim_search.render, win, win.url.get_text(), [], 1, {"order_by":""})
        dynamic_box.pack_start(resolve, True, True, True)
        win.show_all()

        ltext = win.url.get_text()
        win.tabs[win.resolve_tab]["label"].set_text(ltext[:10]+"...")
        win.tabs[win.resolve_tab]["label"].set_tooltip_text(win.url.get_text())
        
    dynamic_box.show_all()
    win.notebook.set_current_page(win.resolve_tab)
    win.resolve_tab = "current"        

# Button to activate seach for those who don't know that you can press Enter    
search_button = Gtk.Button()
search_icon = ui.icon(win, "system-search")
search_button.add(search_icon)
search_button.set_relief(Gtk.ReliefStyle.NONE)
search_button.connect("clicked", search)
win.url.connect("activate", search)
restofpannel.pack_start(search_button, False, False, False)
        
##########################################################################
#                                                                        #
#                           HAMBURGER MENU                               #
#                                                                        #
##########################################################################

# Popover is the new GTK menu thingy that looks like a comic book dialog
# box. Which is what we want here. Because we want it to look nice I suppose.

def on_hamburger(w):


    ################# NOTIFICATIONS #####################
    
    notifications = odysee.get_odysee_notifications(win)

    for i in win.notifications_box.get_children():
        i.destroy()

    if notifications:
        scrl = Gtk.ScrolledWindow()
        scrl.set_size_request(200,200)
        win.notifications_box.pack_start(scrl, 1,1,0)
        
        notbox = Gtk.VBox()
        scrl.add(notbox)

        for i in notifications:
            i = i.get("notification_parameters", {})
            author = i.get("dynamic", {}).get("reply_author")
            publication = i.get("device", {}).get("target")
            comment = i.get("device", {}).get("text")

            # Channel button
            def resolve_channel(win, url):
                out = fetch.lbrynet("resolve", {"urls":url})
                out = out[url]
                return [win, out]
            def render_channel(out):
                win, out = out
                return ui.go_to_channel(win, out)

            notbox.pack_start(Gtk.HSeparator(), 1,1,5)
            
            channel_button = ui.load(win, resolve_channel, render_channel, win, author)
            notbox.pack_start(channel_button, 1,1,5)

            comment_label = Gtk.Label(comment)
            comment_label.set_selectable(True)
            comment_label.set_line_wrap_mode( Gtk.WrapMode.WORD )
            comment_label.set_line_wrap(True)
            comment_label.set_max_width_chars(20)

            def resolve_publication(w, publication):

                win.resolve_tab = "new_tab"
                win.url.set_text(publication)
                win.url.activate()
            
            comment_button = Gtk.Button()
            comment_button.add(comment_label)
            comment_button.connect("clicked", resolve_publication, publication)
            comment_button.set_relief(Gtk.ReliefStyle.NONE)
            notbox.pack_start(comment_button, 1,1,5)
            
        
        win.notifications_box.show_all()
    

hamburger = Gtk.Popover()
hambutton = Gtk.MenuButton(popover=hamburger)
hambutton.connect("clicked", on_hamburger)
hambutton_icon = ui.icon(win, "system-users")
hambutton.add(hambutton_icon)
hambutton.set_relief(Gtk.ReliefStyle.NONE)
pannel.pack_start(hambutton)

# Let's now pack the hamburger menu with items

hambox = Gtk.HBox()


# For the elements inside the box we need a scrolled window, to fit a lot of
# them there.

hamscrl = Gtk.ScrolledWindow()
hamscrl.set_size_request(200,200)
hamburger.add(hambox)

hambox.pack_start(hamscrl, False, False, False)

# "hamchannelbox" will be empty untill the user connects and it loads his channel
# list

hamchannelbox = Gtk.VBox()
hamscrl.add_with_viewport(hamchannelbox)
#hambox.pack_start(hamchannelbox, False, False, False)

###### CHANNELS SELECTOR ########

win.channel = False
def load_channel(win):

    def change_channel(w, win, channel ):
        win.channel = channel
        win.settings["channel"] = win.channel["claim_id"]
        settings.save(win.settings)

        try:
            hambutton.get_child().destroy()
            try:
                newicon = ui.load(win, ui.net_image_calculation, ui.net_image_render, channel["value"]["thumbnail"]["url"], 40, "", False )
            except:
                newicon = ui.icon(win, "system-users")
            hambutton.add(newicon)
            pannel.show_all()
        except Exception as e:
            print("What?", e)
    
    out = fetch.lbrynet("channel_list")
    win.my_channels = out

    # We are chooseing first only if there is no channel set in the settings
    
    
    try:
        first = out["items"][0]
        win.channel = first
    except:
        pass

    if "channel" in win.settings:

        try:
            for i in out["items"]:
                if i["claim_id"] == win.settings["channel"]:
                    first = i
                    break
        except:
            pass
        
    try:
        change_channel(False, win, first)
    except:
        pass
    try:

        
        
        go.set_sensitive(True)
        
        for i in out["items"]:
            channel_button = ui.go_to_channel(win, i, resolve=False)
            channel_button.connect("clicked", change_channel, win, i)
            hamchannelbox.pack_start(channel_button, False, False, False)
        hamchannelbox.show_all()
        second_raw.show_all()
    except Exception as e:
        print("CHANNEL ERROR:", e)

second_raw = Gtk.VBox()
hambox.pack_start(Gtk.VSeparator(), False, False, 5)
hambox.pack_start(second_raw, False, False, False)
        
####### Go to channel button #####

def go_to_channel(w):

    channel_url = win.channel["name"]
    try:
        channel_url = channel_url + "#" + win.channel["claim_id"]
    except:
        pass
            
    win.url.set_text(channel_url)
    win.url.activate()
        
go = Gtk.Button()
b = Gtk.HBox()
b.pack_start(ui.icon(win, "folder-remote"), False, False, False)
b.pack_start(Gtk.Label("  Go To Channel  "), True, True, False)
go.add(b)
go.set_sensitive(False)
go.set_relief(Gtk.ReliefStyle.NONE)
go.connect("clicked", go_to_channel)
second_raw.pack_start(go, False, False, False)

########## UPLOADS BUTTON #########

def load_uploads(w=False):

    dynamic_box = win.tabs[win.notebook.get_current_page()]["box"]
    
    for i in dynamic_box.get_children():
        i.destroy()
    
    send = {"method":"claim_list"}
    resolve = ui.load(win, claim_search.find, claim_search.render, win, "", [], 1, send)
    dynamic_box.pack_start(resolve, True, True, True)
    dynamic_box.show_all()
    
    win.tabs[win.notebook.get_current_page()]["label"].set_text("Uploads")
    win.tabs[win.notebook.get_current_page()]["label"].set_tooltip_text("Uploads")

following = Gtk.Button()
b = Gtk.HBox()
b.pack_start(ui.icon(win, "go-up-symbolic"), False, False, False)
b.pack_start(Gtk.Label("  Uploads  "), True, True, False)
following.add(b)
following.set_relief(Gtk.ReliefStyle.NONE)
following.connect("clicked", load_uploads)
second_raw.pack_start(following, False, False,False)



############## ANALYTICS ################

def load_analytics(w):
    analytics.window(win)

following = Gtk.Button()
b = Gtk.HBox()
b.pack_start(ui.icon(win, "text-csv"), False, False, False)
b.pack_start(Gtk.Label("  Wallet  "), True, True, False)
following.add(b)
following.set_relief(Gtk.ReliefStyle.NONE)
following.connect("clicked", load_analytics)
second_raw.pack_start(following, False, False,False)

second_raw.pack_start(Gtk.HSeparator(), False, False,5)

######## FOLLOWING BUTTON ###########

def load_following(  w=False, mode="following"):

    
    dynamic_box = win.tabs[win.notebook.get_current_page()]["box"]
    
    for i in dynamic_box.get_children():
        i.destroy()
    
    try:
        if not win.subs:
            out = fetch.lbrynet("preference_get")
            win.subs = out["shared"]["value"]["subscriptions"]

        subs_raw = fetch.lbrynet("resolve", {"urls":win.subs})
        subs = []
        for i in subs_raw:
            try:
                subs.append(subs_raw[i]["claim_id"])
            except:
                pass
    except Exception as e:
        print("\n\nERROR:", e, "\n\n")
        subs = []
    
    if mode == "suggest":
        send = {"any_tags":suggest.suggest(),
                "order_by":"trending_mixed"}
        resolve = ui.load(win, claim_search.find, claim_search.render, win, "", [], 1, send)
    else:
        resolve = ui.load(win, claim_search.find, claim_search.render, win, "", subs)

    # Currently live!
    all_lives = livestreams.get_all()
    liveids = []

    if mode != "suggest":
        for livestream in all_lives.get("data", []):
            live_id = livestream.get("ActiveClaim", {}).get("ClaimID", "")
            if livestream.get("ChannelClaimID", "") in subs:
                liveids.append(live_id)
    else:
        for livestream in all_lives.get("data", []):
            live_id = livestream.get("ActiveClaim", {}).get("ClaimID", "")
            liveids.append(live_id)
    
    if liveids:
        send = {"claim_ids":liveids}
        if mode == "suggest":
            send["any_tags"] = suggest.suggest()
        resolve_lives = ui.load(win, claim_search.find, claim_search.render, win, "", [], 1, send)
        lives_frame = Gtk.Expander(label="  Currently Live:  ")
        if mode != "suggest":
            lives_frame.set_expanded(True)
        resolve_lives.set_size_request(350,350)
        lives_frame.add(resolve_lives)
        dynamic_box.pack_start(lives_frame, 0,0,0)

        dynamic_box.pack_start(Gtk.HSeparator(), 0,0,5)
    
    dynamic_box.pack_start(resolve, True, True, True)
    dynamic_box.show_all()

    if mode == "suggest":
        win.tabs[win.notebook.get_current_page()]["label"].set_text("Suggested")
        win.tabs[win.notebook.get_current_page()]["label"].set_tooltip_text("Suggested")
    else:
        win.tabs[win.notebook.get_current_page()]["label"].set_text("Following")
        win.tabs[win.notebook.get_current_page()]["label"].set_tooltip_text("Following")


following = Gtk.Button()
b = Gtk.HBox()
b.pack_start(ui.icon(win, "semi-starred"), False, False, False)
b.pack_start(Gtk.Label("  Suggested  "), True, True, False)
following.add(b)
following.set_relief(Gtk.ReliefStyle.NONE)
following.connect("clicked", load_following, "suggest")
second_raw.pack_start(following, False, False,False)
    
following = Gtk.Button()
b = Gtk.HBox()
b.pack_start(ui.icon(win, "emblem-favorite"), False, False, False)
b.pack_start(Gtk.Label("  Following  "), True, True, False)
following.add(b)
following.set_relief(Gtk.ReliefStyle.NONE)
following.connect("clicked", load_following)
second_raw.pack_start(following, False, False,False)


######## TRENDING BUTTONS ###########

def load_trending(w=False, articles=False):

    dynamic_box = win.tabs[win.notebook.get_current_page()]["box"]
    
    for i in dynamic_box.get_children():
        i.destroy()
    
    send = {"order_by":"trending_mixed"}
    if articles:
        send["media_types"] = ["text/markdown"]
    resolve = ui.load(win, claim_search.find, claim_search.render, win, "", [], 1, send)
    dynamic_box.pack_start(resolve, True, True, True)
    dynamic_box.show_all()

    if articles:
        lname = "Articles"
    else:
        lname = "Trending"
    

    win.tabs[win.notebook.get_current_page()]["label"].set_text(lname)
    win.tabs[win.notebook.get_current_page()]["label"].set_tooltip_text(lname)
        
    
    
following = Gtk.Button()
b = Gtk.HBox()
                          # The other one was showing web-browsers at some themes
b.pack_start(ui.icon(win, "emblem-shared"), False, False, False)
b.pack_start(Gtk.Label("  Trending  "), True, True, False)
following.add(b)
following.set_relief(Gtk.ReliefStyle.NONE)
following.connect("clicked", load_trending)
second_raw.pack_start(following, False, False,False)

following = Gtk.Button()
b = Gtk.HBox()
b.pack_start(ui.icon(win, "text-x-generic"), False, False, False)
b.pack_start(Gtk.Label("  Articles  "), True, True, False)
following.add(b)
following.set_relief(Gtk.ReliefStyle.NONE)
following.connect("clicked", load_trending, True)
second_raw.pack_start(following, False, False,False)

#### LIVESTREAMS ####

def load_livestreams(w):

    # First let's fetch the data about all livestreams

    all_lives = livestreams.get_all()
    liveids = []
    for livestream in all_lives.get("data", []):
        live_id = livestream.get("ActiveClaim", {}).get("ClaimID", "")
        liveids.append(live_id)

    # Then we gonna search all the liveids

    dynamic_box = win.tabs[win.notebook.get_current_page()]["box"]
    
    for i in dynamic_box.get_children():
        i.destroy()
    
    send = {"claim_ids":liveids}
    
    resolve = ui.load(win, claim_search.find, claim_search.render, win, "", [], 1, send)
    dynamic_box.pack_start(resolve, True, True, True)
    dynamic_box.show_all()

    lname = "Live Streams"
    

    win.tabs[win.notebook.get_current_page()]["label"].set_text(lname)
    win.tabs[win.notebook.get_current_page()]["label"].set_tooltip_text(lname)
    
        
    
following = Gtk.Button()
b = Gtk.HBox()
b.pack_start(ui.icon(win, "emblem-new"), False, False, False)
b.pack_start(Gtk.Label("  Live Streams  "), True, True, False)
following.add(b)
following.set_relief(Gtk.ReliefStyle.NONE)
following.connect("clicked", load_livestreams)
second_raw.pack_start(following, False, False,False)


second_raw.pack_start(Gtk.HSeparator(), False, False,5)

######## DOWNLOADS #########

def load_downloads(w):
    downloads.window(win)

following = Gtk.Button()
b = Gtk.HBox()
b.pack_start(ui.icon(win, "go-down-symbolic"), False, False, False)
b.pack_start(Gtk.Label("  Downloads  "), True, True, False)
following.add(b)
following.set_relief(Gtk.ReliefStyle.NONE)
following.connect("clicked", load_downloads)
second_raw.pack_start(following, False, False,False)



second_raw.pack_start(Gtk.HSeparator(), False, False,5)

######## SETTINGS BUTTON ############

second_raw.pack_start(Gtk.HSeparator(), False, False,5)

settings_button = Gtk.Button()
b = Gtk.HBox()
b.pack_start(ui.icon(win, "preferences-system"), False, False, False)
b.pack_start(Gtk.Label("  Settings  "), True, True, False)
settings_button.add(b)
settings_button.set_relief(Gtk.ReliefStyle.NONE)
settings_button.connect("clicked", settings.dialogue, win)
second_raw.pack_start(settings_button, False, False, False)

second_raw.pack_start(Gtk.HSeparator(), False, False,5)

########## FORCE SEARCH BUTTON #######

force_search_box = Gtk.HBox()
force_search = Gtk.Switch()
force_search_box.pack_end(force_search, False, False, 0)
force_search_box.pack_start(ui.icon(win, "system-search"), False, False, 0)
force_search_box.pack_start(Gtk.Label("  Force Search  "), True, True, 0)
force_search.set_tooltip_text("If not activated it will try to resolve the claim first.")
second_raw.pack_start(force_search_box, False, False, False)


###### THE BOX FOR THE NOTIFICATIONS #####

win.notifications_box = Gtk.VBox()
hambox.pack_start(Gtk.VSeparator(), False, False, 5)
hambox.pack_start(win.notifications_box, False, False, False)
hambox.show_all()

##########################################################################
#                                                                        #
#                           DYNAMIC BOX ( REST )                         #
#                                                                        #
##########################################################################

# Dynamic box is a box contents of which will change depending on the "page"
# that the user is loading.

box = Gtk.VBox() # I'm making a top level box just in case
win.add(box)


win.notebook.set_scrollable(True)

def new_tab():
    dynamic_box = Gtk.VBox() # And here our dynamic box

    label = Gtk.Label("Tab "+str(len(win.tabs)+1))

    

    kill = Gtk.Button()
    
    kill.add(ui.icon(win, "delete"))
    kill.set_relief(Gtk.ReliefStyle.NONE)

    box = Gtk.HBox()
    box.pack_start(label, False, False, 5)
    box.pack_start(kill, False, False, 0)
    box.show_all()
    
    tab = {"box":dynamic_box, "label":label, "index":len(win.tabs)}

    def on_kill(w, tab):

        if len(win.tabs) == 1:
            load_following(mode=win.settings["default_tab"])
            return
        
        i = tab["index"]
        win.notebook.remove_page(i)
        del win.tabs[i]

        for r, t in enumerate(win.tabs):
            t["index"] = r

        
        
    kill.connect("clicked", on_kill, tab)
    
    win.tabs.append(tab)
    win.resolve_tab = len(win.tabs) - 1

    win.notebook.append_page(win.tabs[-1]["box"], box)
    
    
    
new_tab()
             
box.pack_start(win.notebook, True, True, False)



# Just something to run if we are connected

if win.SDK_running == 1:
    load_following(mode=win.settings["default_tab"])
    load_channel(win)
else:
    win.tabs[0]["box"].pack_start(Gtk.Label("LBRY is not connected. Please connect."), True, True, 20)

##########################################################################
#                                                                        #
#                              DRAG AND DROP                             #
#                                                                        #
##########################################################################

def on_drop(widget, drag_context, x, y, data, info, time):

    win.url.set_text(data.get_text())
    win.url.activate()

    
enforce_target = Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags(4), 129)
box.drag_dest_set(Gtk.DestDefaults.ALL, [enforce_target], Gdk.DragAction.COPY)
box.connect("drag-data-received", on_drop)


    
# Starting Everything
    
win.show_all()
Gtk.main()

#### Clearing the cache of images ###

ui.clean_image_cache()
